package com.meilai.project.service.system.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilai.project.entity.personnel.org.Role;
import com.meilai.project.entity.system.*;
import com.meilai.project.mapper.system.RouterMapper;
import com.meilai.project.service.personnel.org.RoleService;
import com.meilai.project.service.system.*;
import com.meilai.project.util.TreeUtil;
import com.meilai.project.vo.TreeVO;
import com.meilai.project.vo.system.BTNRightVO;
import com.meilai.project.vo.system.RightVO;
import com.meilai.project.vo.system.RouterMetaVO;
import com.meilai.project.vo.system.RouterVO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author 张驰
 * @date 2020/9/10 17:37
 */
@Service
public class RouterServiceImpl extends ServiceImpl<RouterMapper, Router> implements RouterService {

    @Autowired
    private RoleService roleService;

    @Autowired
    private UserRoleRelationService userRoleRelationService;

    @Autowired
    private RoleRouterRelationService roleRouterRelationService;
    @Autowired
    private RouterMapper routerMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private RouterService routerService;

    @Override
    public List<Router> select2TopById(long id){
        List<Router> list = new ArrayList<>();
        selectTree(id,list);
        return list;
    }

    private void selectTree(long id,List<Router> list){
        Router router = routerMapper.selectById(id);
        list.add(router);
        if(router.getPid()!=null&&router.getPid()!=0){
            selectTree(router.getPid(),list);
        }
    }

    @Override
    public List<RouterVO> findMenuByUserId(long userId){
        User user = userService.getById(userId);
        if("admin".equals(user.getUsername())){
            return toVOList(routerMapper.findByType(1),2l);
        }
        List<Router> routers = routerMapper.findByUserId(userId,1);
        List<Router> list = getRouterListByIdsAndType(routers.stream().map(r->r.getId()).collect(Collectors.toList()), 1);
        if(list.size()<=0) return new ArrayList<>();

        // 将List<Router>转换成List<RouterVO>
        return toVOList(list,null);
    }

    @Override
    public List<BTNRightVO> findBTNByUserId(long userId){
        User user = userService.getById(userId);
        List<Router> routers = null;
        if("admin".equals(user.getUsername())){
            routers = routerMapper.findByType(2);
        }else{
            routers = routerMapper.findByUserId(userId,2);
        }
        if(routers.size()<=0) return new ArrayList<>();
        return routers.stream().map(item -> {
            BTNRightVO vo = new BTNRightVO();
            BeanUtils.copyProperties(item, vo);
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<RouterVO> getRoutersByUserId(Long userId) {
        List<RouterVO> returnList = new ArrayList<>();

        List<Long> roleIds = getRoleIdsByUserId(userId);
        if(roleIds.size() <= 0) return returnList;

        // web首页的角色
        Role firstRole = new Role();
        List<UserRoleRelation> userRoleRelationList = userRoleRelationService.list(new QueryWrapper<UserRoleRelation>().eq("user_id",userId).in("role_id",roleIds).eq("is_index",1));
        if(userRoleRelationList != null && userRoleRelationList.size() > 0){
            firstRole  = roleService.getOne(new QueryWrapper<Role>().eq("id",userRoleRelationList.get(0).getRole_id()));
        }


        List<Long> routerIds = getRouterIdsByRoleIds(roleIds);
        if(routerIds.size() <= 0) return returnList;

        List<Router> list = getRouterListByIdsAndType(routerIds, 1);
        if(list.size()<=0) return returnList;

        // 将List<Router>转换成List<RouterVO>
        return toVOList(list,firstRole.getIndex_page_id());
    }

    private List<Long> getRoleIdsByUserId(Long userId){
        List<Long> returnIds = new ArrayList<>();

        // 根据用户id查询角色idList
        List<Long> roleIds = new ArrayList<>();
        List<UserRoleRelation> list = userRoleRelationService.list(new QueryWrapper<UserRoleRelation>().eq("user_id",userId));
        if(list != null){
            roleIds = list.stream().map(UserRoleRelation::getRole_id).collect(Collectors.toList());
        }

        // 过滤掉已删除和已禁用的角色
        List<Role> roles = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(roleIds))roles = roleService.list(new QueryWrapper<Role>().in("id",roleIds).isNull("deleted_at").eq("status",1));
        if(CollectionUtils.isEmpty(roles)) return returnIds;

        return roles.stream().map(Role::getId).collect(Collectors.toList());
    }

    private List<Long> getRouterIdsByRoleIds(List<Long> roleIds){
        List<Long> returnIds = new ArrayList<>();

        // 根据角色idList，得到路由数据List<Router>
        List<Long> routerIds = new ArrayList<>();
        List<RoleRouterRelation> list = roleRouterRelationService.list(new QueryWrapper<RoleRouterRelation>().in("role_id",roleIds));
        if(list != null){
            routerIds = list.stream().map(RoleRouterRelation::getRouter_id).collect(Collectors.toList());
        }

        // 过滤掉已删除和已禁用的权限
        List<Router> routers = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(routerIds)) routers = list(new QueryWrapper<Router>().in("id",routerIds).isNull("deleted_at").eq("status",1));
        if(CollectionUtils.isEmpty(routers)) return returnIds;

        return routers.stream().map(Router::getId).collect(Collectors.toList());
    }

    private List<Router> getRouterListByIdsAndType(List<Long> routerIds, Integer type){
        List<Router> routerList = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(routerIds)) routerList = list(new QueryWrapper<Router>().in("id",routerIds).eq("type",type).isNull("deleted_at").eq("status",1).orderByAsc("pid","sort"));
        return (routerList == null || routerList.size()<=0)? new ArrayList<>():routerList;
    }

    /**
     * 将路由list 转换成 树
     * @param list 路由list
     */
    private List<RouterVO> toVOList(List<Router> list, Long indexPageId){
        List<RouterVO> returnList = new ArrayList<>();
        if(list == null || list.size()<=0) return returnList;

        // 设置首页
        boolean hasFirstFlag = true;
        if(indexPageId != null){
            RouterVO index = baseMapper.getIndexPageByRouterId(indexPageId);
            if(index != null) returnList.add(index);
            else hasFirstFlag = false;
        }else{
            hasFirstFlag = false;
        }

        //分组
        boolean finalHasFirstFlag = hasFirstFlag;
        Map<Long, List<RouterVO>> collect = list.stream().map(item -> {
            RouterVO vo = new RouterVO();
            BeanUtils.copyProperties(item,vo);
            RouterMetaVO meta = new RouterMetaVO();
            meta.setTitle(item.getTitle());
            meta.setIcon(item.getIcon());
            if(finalHasFirstFlag && item.getId().equals(indexPageId)) meta.setAffix(true);
            vo.setMeta(meta);
            return vo;
        }).collect(Collectors.groupingBy(RouterVO::getPid));

        // pid=0的顶级菜单
        returnList.addAll(collect.get(0L));
        returnList.forEach(root -> {
            TreeForEach(collect,root);
        });

        if(!hasFirstFlag){
            // 用户未设置首页时，取菜单第一页作为首页
            if(returnList.size() > 0) {
                RouterVO _index = baseMapper.getIndexPageByRouterId(getFirstMenuId(returnList));
                if(_index != null) {
                    _index.getMeta().setAffix(true);
                    returnList.add(0, _index);
                }
            }
        }

        return returnList;
    }

    private Long getFirstMenuId(List<RouterVO> menu){
        List<RouterVO> children = menu.get(0).getChildren();
        if(children != null && children.size() > 0) return getFirstMenuId(children);
        else return menu.get(0).getId();
    }

    private static void TreeForEach(Map<Long, List<RouterVO>> collect, RouterVO treeMenuNode) {
        List<RouterVO> treeMenuNodes = collect.get(treeMenuNode.getId());
        if(collect.get(treeMenuNode.getId())!=null){
            //排序
            treeMenuNodes.sort((u1, u2) -> u1.getSort().compareTo(u2.getSort()));
            treeMenuNodes.stream().sorted(Comparator.comparing(RouterVO::getSort)).collect(Collectors.toList());
            treeMenuNode.setChildren(treeMenuNodes);
            treeMenuNode.getChildren().forEach(t->{
                TreeForEach(collect,t);
            });
        }
    }

    @Override
    public List<BTNRightVO> getBTNRightByUserId(Long userId) {
        List<BTNRightVO> returnList = new ArrayList<>();

        List<Long> roleIds = getRoleIdsByUserId(userId);
        if(roleIds.size() <= 0) return returnList;

        List<Long> routerIds = getRouterIdsByRoleIds(roleIds);
        if(routerIds.size() <= 0) return returnList;

        List<Router> list = getRouterListByIdsAndType(routerIds, 2);
        if(list.size()<=0) return returnList;

        return list.stream().map(item -> {
            BTNRightVO vo = new BTNRightVO();
            BeanUtils.copyProperties(item, vo);
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<TreeVO> getRights() {
        List<TreeVO> returnList = new ArrayList<>();
        List<Router> routers = getRouterListByType();
        if(routers.size() <=0 ) return returnList;
        return getTreeVOByRouters(routers);
    }

    @Override
    public List<TreeVO> getRouterRights() {
        List<TreeVO> returnList = new ArrayList<>();
        List<Router> routers = getRouterListByType(1);
        if(routers.size() <=0 ) return returnList;
        return getTreeVOByRouters(routers);
    }

    private List<Router> getRouterListByType(Integer ... type){
        List<Router> routers = new ArrayList<>();
        if(type != null && type.length == 1) {
            routers =list(new QueryWrapper<Router>().isNull("deleted_at").and(i -> i.isNull("hidden").or(j -> j.ne("hidden","true"))).eq("type",type[0]).orderByAsc("sort","pid","id"));
        }else{
            routers =list(new QueryWrapper<Router>().isNull("deleted_at").and(i -> i.isNull("hidden").or(j -> j.ne("hidden","true"))).orderByAsc("sort","pid","id"));
        }
        return routers!=null?routers:new ArrayList<>();
    }

    private List<TreeVO> getTreeVOByRouters(List<Router> routers){

        List<Long> rightVOIds = routers.stream().map(Router::getId).collect(Collectors.toList());

        List<RightVO> rights = baseMapper.getRightVOs(rightVOIds);

        // 分组
        Map<Long, List<TreeVO>> collect = rights.stream().filter(item -> item.getStatus()==1).map(item -> {
            TreeVO vo = new TreeVO();
            BeanUtils.copyProperties(item,vo);
            vo.setLabel(item.getTitle());
            return vo;
        }).collect(Collectors.groupingBy(TreeVO::getPid));

        // pid=0的顶级菜单
        List<TreeVO> returnList = new ArrayList<>(collect.get(0L));
        returnList.forEach(root -> {
            TreeUtil.TreeForEachUseSort(collect,root);
        });

        returnList.sort(new Comparator<TreeVO>() {
            @Override
            public int compare(TreeVO o1, TreeVO o2) {
                return o1.getSort() - o2.getSort();
            }
        });

        return returnList;
    }
}
